Java Optional 实例介绍
(给ImportNew加星标,提高Java技能)
编译:ImportNew/唐尤华
dzone.com/articles/java-optional
Optional 是一种容器对象,可能包含也可能不含非 null 值。如果包含某个值 isPresent() 返回 true,调用get()返回该值。
Package : java.util
public final class Optional<T> extends Object
以下是 Optional 类中一些有用的方法列表:
1. 创建 Optional 相关方法
方法:Optional.of、Optional.ofNullable、Optional.empty():
Optional<String> emptyOptional = Optional.empty();
Optional<String> nonEmptyOptional = Optional.of("name"); // 对 null 无效
Optional<String> nonEmptyOptional = Optional.ofNullable(null); // 支持 null
2. 检查 Optional 值
方法:Optional.isPresent()、Optional.ifPresent()
如果 Optional有值,isPresent() 返回 true
Optional<String> nonEmptyOptional = Optional.of("name");
assertTrue(nonEmptyOptional.isPresent());
ifPresent() = 如果值存在,则执行代码块
在 Optional 出现前,需要在方法内进行以下 null 检查。
if(data == null){
System.out.println( " data is " + data);
}
// data 是方法内部使用的对象
由于无法确保data在使用前进行了 null 检查,可能会抛出 NullPointerException。
现在,引入Optional 后,可以用 ifPresent满足类似需求。
Optional<String> nonEmptyOptional = Optional.of("name");
nonEmptyOptional.ifPresent( x-> { System.out.println(x.length()); } );
3. 通过 Optional 取值
get() = 返回值包含在 Optional 中返回
Optional<String> nonEmptyOptional = Optional.ofNullable("orignal");
String value = nonEmptyOptional.get();
orElse() = 如果值不存在,则返回默认值
// Optional 包含 null 时, 使用 orElse 值
Optional<String> emptyOptional = Optional.ofNullable(null);
String value = emptyOptional.orElse("default Value");
assertEquals("default Value", value);
// Optional 不包含 null 时, 不使用 orElse 值
Optional<String> nonEmptyOptional = Optional.ofNullable("orginal");
String value1 = nonEmptyOptional.orElse("default Value");
assertEquals("orginal", value1);
orElseGet() = 与 orElse() 类似,如果 Optional 不包含值,用函数作为返回值
// Optional 包含 null 时, 使用 orElse
Optional<String> emptyOptional = Optional.ofNullable(null);
String value = emptyOptional.orElseGet(()->"default value");
assertEquals("default value", value);
// Optional 不包含 null 时, 不使用 orElse
Optional<String> nonEmptyOptional = Optional.ofNullable("orginal");
String value1 = nonEmptyOptional.orElseGet(()->"default value");
assertEquals("orginal", value1);
orElseThrow() = 与 orElseGet() 类似,监测到值为 null 时抛出异常
@Test(expected = NullPointerException.class)
public void OrElseThrowCheck() {
String nullName = null;
String value = Optional.ofNullable(nullName).orElseThrow(NullPointerException::new);
}
4. Optional 用法
使用 Optional 作为返回值
Optional 的常见用法是作为方法返回值。定义方法时,可以根据实现逻辑返回 null 或对象。返回 Optional 对象是一种很好的方法,开发人员知道返回值可能是 null,迫使他们合理地处理返回的对象。Optional 的优点在于,能够引导开发者进行恰当的检查,从而避免 NullPointerException。
下面的例子定义了 Optional<Employee>getEmployeeWithId(int id) 方法,返回值类型为 Optional<Employee>。调用者需要通过 Optional 方法得到返回值。执行过程中可以避免 NullPointerExceptions。
static List<Employee> employess = new ArrayList<>();
public static void main(String[] args) throws EmployeeNotFoundException {
employess.add(new Employee("emp1", 1, 1000));
employess.add(new Employee("emp2", 2, 2000));
employess.add(new Employee("emp1", 3, 3000));
Optional<Employee> employee = getEmployeeWithId(1);
Employee e = employee.orElseThrow(() -> new EmployeeNotFoundException("emp not found"));
System.out.println(e);
}
public static Optional<Employee> getEmployeeWithId(int id) {
Optional<Employee> employee = employess.stream().filter(e -> (e.getId() == id)).findFirst();
return employee;
}
使用 Optional 作为方法参数
不推荐使用Optional 作为方法参数。假设一个方法包含两个参数:一个类型是 Optional,另一个类型是非 Optional。背后的逻辑是,第一个参数值可能为 null。
这种情况,不要使用 Optional 作为参数,请进行方法重载。
上面的例子最好定义重载方法,只接受一个参数。
public static Optional<Employee> getEmployee(int id,Optional<String> name) {
...
return employee;
}
// 更好的方法: 重载方法
public static Optional<Employee> getEmployee(int id,String name)
public static Optional<Employee> getEmployee(int id)
5. Java 各版本新增的 Optional 方法列表
Java 9
or():如果值存在,返回包含该值的 Optional 对象;否则,返回 or() 函数生成的 Optional 对象。
ifPresentOrElse(Consumer<? super T>action, Runnable emptyAction):如果值存在,使用该值执行指定调用,否则使用空值执行调用。
stream():如果值存在,返回该值的顺序流(Stream);否则返回空流。
Java 10
orElseThrow():如果值存在,返回该值;否则抛出 NoSuchElementException。注意:与 Java 8 不同,不接受任何参数。
Java 11
isEmpty():如果值不存在,返回 true;否则返回 false。
6. 完整代码
源代码请参考下面 Git 链接:
源代码:方法 “getEmployeeWithId” 返回 Optional<Employee>
源代码:Optional 方法测试用例
说明:Optional 是基于值的类,应当避免对Optional 对象调用像引用相等性(==)、HashCode、同步等基于对象标识的操作,调用可能产生无法预测的结果。
7. 参考文档
以下是不同 Java 版本的参考文档:
推荐阅读
(点击标题可跳转阅读)
看完本文有收获?请转发分享给更多人
关注「ImportNew」,提升Java技能
好文章,我在看❤️